Owen Sullivan

Memory Leak Detector:
* DESCRIPTION: A program which uses popen() to run an external program 
(passed as a command-line argument), substituting calls to malloc() and free() 
with a custom shim library, and lists any memory leaks (designated by 
calls to malloc() that are not subsequently freed using free()).
* KNOWN PROBLEMS:
** In the extremely unlikely event that either the full memory address supplied 
to/by a malloc() or free() call or number of bytes supplied to a malloc() call 
exceeds 1000 characters, the problem will fail to read the information printed 
by the shim library. This is because of a fixed character array buffer size 
within the leakcount program. This limitation should not affect the shim 
library's functionality, only the leakcount program.
** Some Linux-based systems running older versions of GCC may experience an 
issue using dlsym() to find the next function pointer to malloc() or free() as 
used in the shim library. This could be caused by the lack of explicit 
reference to the stdlib.h header library, which is not included within the 
shim library because including it may have been causing intermittent issues. 
Modern versions of GCC should include a version of libc that works as 
intended with dlsym, and this issue will likely never be a problem, but it's 
worth mentioning.
** The shim library may seg fault if stderr is closed by the child process 
spawned by popen() in leakcount. This is unrecoverable in the current 
implementation because the shim library requires printing to stderr for the 
leakcount program to interpret information about calls to malloc() and free().
** Any output printed to stderr by the program which is being tested for 
memory leaks will be redirected to leaks.db and will not be printed to 
the terminal until slightly after the child process spawned by popen() has 
finished executing.
** In the extremely unlikely event that the program being tested for memory 
leaks prints a single line of output in the format "<address>,<size>\n" 
to stderr, leakcount will count that line as a call to malloc() or free() and 
this could result in leakcount misreporting memory leaks.
* DESIGN:
** memshim.c, which compiles into memory_shim.so, is a shim library that 
intercepts calls to malloc() and free() and prints the memory addresses and 
sizes (for malloc()) to stderr.
** leakcount.c, which compiles into leakcount, spawns a child process using 
popen() that sets the LD_PRELOAD environment variable to use memory_shim.so 
while also redirecting the child process's stderr output to a file called 
leaks.db. leakcount then reads the contents of leaks.db and separates 
memory addresses and sizes, matches memory addresses where matches can be 
found, and treats non-matches as memory leaks.
** leaks.db will contain memory addresses and sizes formatted like the 
following: "<address>,<size>\n" for malloc() and free() calls.

System Call Tracer:
* DESCRIPTION: A program which traces system calls by a child process spawned 
with execvp(), counts them, and prints them to an output file.
* KNOWN PROBLEMS:
** If the first (or second, depending on how you count) command-line argument 
passed to sctracer includes any instances of double-spaces (two spaces in a 
row in the string), sctracer will fail to parse the full string of command-line 
arguments and will fail to run the child process with all of the expected 
command-line arguments. This could be fixed with more comprehensive parsing 
logic, but, quite frankly, if anyone is testing the program with two spaces in 
their command-line arguments then they're doing it wrong.
** There might be some UNIX-based systems with certain compiler versions that 
do not include "sys/reg.h", and thus the program either won't compile (if 
compiling from source) or won't run as intended because the "ORIG_RAX" macro 
is unavailable.
* DESIGN:
** sctracer.c, which compiles into sctracer, forks and spawns a child process 
using execvp() that's primed to be traced by ptrace(). sctracer splits argv[1] 
into multiple command-line arguments in the case of a space-separated string, 
runs the program supplied by said command-line argument, then traces system 
calls made by the child process. The program determines whether or not a 
system call is unique to the trial run and counts it accordingly.
** I found an online reference which demonstrated how loops can be used to 
continually check for SIGSTOP interrupt signals, as opposed to only handing one 
system call (like Dr. Sorber's example), and I based some of my functionality 
on that reference. After speaking with Dr. Sorber, it's clear that this method 
may be one of the only ways to do it, but here's the reference just to show 
that I didn't straight-up plagiarise:
*** https://blog.nelhage.com/2010/08/write-yourself-an-strace-in-70-lines-of-code/